#include <iostream>
#include <omp.h>

// 定义类 T
class T {
public:
    int val;
    
    // 构造函数
    T (int v) {
        val = v;
    }
    
    // 拷贝构造函数
    T (const T& t) {
        val = t.val;
    }
};

// 对两个T对象执行操作
void g(T& a, T& b) {
    a.val += b.val;
}

// 全局变量
int x = 1;
T a(x);
const T b_aux(x); // 捕获 x 的值 = 1
T b(b_aux);
#pragma omp threadprivate(a, b)

// 函数f增加x的值
void f(int n) {
    x++;
}

int main() {
    int n = 5; // 设置循环次数

    // 打印初始值
    std::cout << "初始值:" << std::endl;
    std::cout << "x = " << x << std::endl;
    std::cout << "a.val = " << a.val << std::endl;
    std::cout << "b.val = " << b.val << std::endl;
    std::cout << std::endl;

    // 设置线程数
    int num_threads = 4;
    omp_set_num_threads(num_threads);

    // 第一个并行区域
    std::cout << "第一个并行区域:" << std::endl;
    #pragma omp parallel
    {
        int tid = omp_get_thread_num();
        #pragma omp critical
        {
            std::cout << "线程 " << tid << ": a.val = " << a.val << ", b.val = " << b.val << std::endl;
        }

        // 对当前线程的a和b执行g操作
        g(a, b);
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << " 执行g后: a.val = " << a.val << ", b.val = " << b.val << std::endl;
        }
    }

    // 修改主线程的x值
    f(n);
    std::cout << "\n执行f(n)后, 主线程: x = " << x << std::endl;
    std::cout << "主线程: a.val = " << a.val << ", b.val = " << b.val << std::endl;

    // 执行并行循环
    std::cout << "\n执行parallel for循环:" << std::endl;
    #pragma omp parallel for
    /* 在每个线程:
     * a 是从 x 构造的 (值为 1 或 2?)
     * b 是从 b_aux 拷贝构造的
     */
    for (int i=0; i<n; i++) {
        int tid = omp_get_thread_num();
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << ", 迭代 " << i 
                      << ": 开始时 a.val = " << a.val << ", b.val = " << b.val << std::endl;
        }
        
        g(a, b); /* a的值是未指定的 */
        
        #pragma omp critical
        {
            std::cout << "线程 " << tid << ", 迭代 " << i 
                      << ": 执行g后 a.val = " << a.val << ", b.val = " << b.val << std::endl;
        }
    }

    // 检查主线程的最终值
    std::cout << "\n最终状态:" << std::endl;
    std::cout << "主线程: a.val = " << a.val << ", b.val = " << b.val << std::endl;

    return 0;
}